From b54e5f4ca17d56f4844caa9485989f65b18babda Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sat, 2 Mar 2002 20:37:07 +0000 Subject: [PATCH] Robustify tracking of pointer grab window. Fri Mar 1 18:39:44 2002 Owen Taylor * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, gdkwindow-x11.c}: Robustify tracking of pointer grab window. * gdk/x11/gdkmain-x11.c: Keep track of current keyboard grab window. * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk API for finding out current grab information. * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events so that the effective behavior of owner_events = TRUE is changed to "deliver events to same window group normally" instead of "deliver events to same application normally. #69934 * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that it works within the GtkList combo, where there is a owner_events = FALSE gdk_pointer_grab() already in effect. (#65006, reported by Damon Chaplin) --- ChangeLog | 22 ++++++ ChangeLog.pre-2-0 | 22 ++++++ ChangeLog.pre-2-10 | 22 ++++++ ChangeLog.pre-2-2 | 22 ++++++ ChangeLog.pre-2-4 | 22 ++++++ ChangeLog.pre-2-6 | 22 ++++++ ChangeLog.pre-2-8 | 22 ++++++ gdk/x11/gdkevents-x11.c | 5 +- gdk/x11/gdkmain-x11.c | 151 ++++++++++++++++++++++++++++++++++++++- gdk/x11/gdkprivate-x11.h | 8 +-- gdk/x11/gdkwindow-x11.c | 15 +++- gtk/gtkmain.c | 133 +++++++++++++++++++++++++++++++++- gtk/gtkrange.c | 20 +++++- 13 files changed, 470 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index a78504b443..5fc8dfbc55 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,25 @@ +Fri Mar 1 18:39:44 2002 Owen Taylor + + * gdk/x11/{gdkevents-x11.c,gdkmain-x11.c,gdkprivate-x11.h, + gdkwindow-x11.c}: Robustify tracking of pointer grab window. + + * gdk/x11/gdkmain-x11.c: Keep track of current keyboard + grab window. + + * gdk/x11/gdkmain-x11.c (gdk_pointer_grab_info_libgtk_only, + gdk_keyboard_grab_info_libgtk_only): Private libgtk => libgtk + API for finding out current grab information. + + * gtk/gtkmain.c (rewrite_event_for_grabs): Rewrite events + so that the effective behavior of owner_events = TRUE is changed + to "deliver events to same window group normally" instead + of "deliver events to same application normally. #69934 + + * gtk/gtkrange.c: Use an explicit gtk_grab_add() so that + it works within the GtkList combo, where there is a + owner_events = FALSE gdk_pointer_grab() already in effect. + (#65006, reported by Damon Chaplin) + Sat Mar 2 14:32:50 2002 Owen Taylor * configure.in: Default to --disable-gtk-doc (avoid Jade diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 2d1e14bd58..babd7e35c8 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -1262,9 +1262,8 @@ gdk_event_translate (GdkEvent *event, gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_ICONIFIED); - - if (_gdk_xgrab_window == window_private) - _gdk_xgrab_window = NULL; + + _gdk_xgrab_check_unmap (window, xevent->xany.serial); break; diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index b6383a0dd4..0b87d8c0c0 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -92,6 +92,18 @@ static gboolean gdk_synchronize = FALSE; static GSList *gdk_error_traps = NULL; /* List of error traps */ static GSList *gdk_error_trap_free_list = NULL; /* Free list */ +/* Information about current pointer and keyboard grabs held by this + * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window + * window is NULL, then the other associated fields are ignored + */ +static GdkWindowObject *gdk_pointer_xgrab_window = NULL; +static gulong gdk_pointer_xgrab_serial; +static gboolean gdk_pointer_xgrab_owner_events; + +static GdkWindowObject *gdk_keyboard_xgrab_window = NULL; +static gulong gdk_keyboard_xgrab_serial; +static gboolean gdk_keyboard_xgrab_owner_events; + GdkArgDesc _gdk_windowing_args[] = { { "display", GDK_ARG_STRING, &_gdk_display_name, (GdkArgFunc)NULL }, { "sync", GDK_ARG_BOOL, &gdk_synchronize, (GdkArgFunc)NULL }, @@ -251,6 +263,7 @@ gdk_pointer_grab (GdkWindow * window, Window xwindow; Window xconfine_to; Cursor xcursor; + unsigned long serial; int i; g_return_val_if_fail (window != NULL, 0); @@ -260,6 +273,7 @@ gdk_pointer_grab (GdkWindow * window, cursor_private = (GdkCursorPrivate*) cursor; xwindow = GDK_WINDOW_XID (window); + serial = NextRequest (GDK_WINDOW_XDISPLAY (window)); if (!confine_to || GDK_WINDOW_DESTROYED (confine_to)) xconfine_to = None; @@ -308,7 +322,11 @@ gdk_pointer_grab (GdkWindow * window, } if (return_val == GrabSuccess) - _gdk_xgrab_window = (GdkWindowObject *)window; + { + gdk_pointer_xgrab_window = (GdkWindowObject *)window; + gdk_pointer_xgrab_serial = serial; + gdk_pointer_xgrab_owner_events = owner_events; + } return gdk_x11_convert_grab_status (return_val); } @@ -334,7 +352,7 @@ gdk_pointer_ungrab (guint32 time) _gdk_input_ungrab_pointer (time); XUngrabPointer (gdk_display, time); - _gdk_xgrab_window = NULL; + gdk_pointer_xgrab_window = NULL; } /* @@ -355,7 +373,36 @@ gdk_pointer_ungrab (guint32 time) gboolean gdk_pointer_is_grabbed (void) { - return _gdk_xgrab_window != NULL; + return gdk_pointer_xgrab_window != NULL; +} + +/** + * gdk_pointer_grab_info_libgtk_only: + * @grab_window: location to store current grab window + * @owner_events: location to store boolean indicating whether + * the @owner_events flag to gdk_pointer_grab() was %TRUE. + * + * Determines information about the current pointer grab. + * This is not public API and must not be used by applications. + * + * Return value: %TRUE if this application currently has the + * pointer grabbed. + **/ +gboolean +gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events) +{ + if (gdk_pointer_xgrab_window) + { + if (grab_window) + *grab_window = (GdkWindow *)gdk_pointer_xgrab_window; + if (owner_events) + *owner_events = gdk_pointer_xgrab_owner_events; + + return TRUE; + } + else + return FALSE; } /* @@ -384,10 +431,13 @@ gdk_keyboard_grab (GdkWindow * window, guint32 time) { gint return_val; + unsigned long serial; g_return_val_if_fail (window != NULL, 0); g_return_val_if_fail (GDK_IS_WINDOW (window), 0); + serial = NextRequest (GDK_WINDOW_XDISPLAY (window)); + if (!GDK_WINDOW_DESTROYED (window)) { #ifdef G_ENABLE_DEBUG @@ -404,6 +454,13 @@ gdk_keyboard_grab (GdkWindow * window, else return_val = AlreadyGrabbed; + if (return_val == GrabSuccess) + { + gdk_keyboard_xgrab_window = (GdkWindowObject *)window; + gdk_keyboard_xgrab_serial = serial; + gdk_keyboard_xgrab_owner_events = owner_events; + } + return gdk_x11_convert_grab_status (return_val); } @@ -426,6 +483,94 @@ void gdk_keyboard_ungrab (guint32 time) { XUngrabKeyboard (gdk_display, time); + gdk_keyboard_xgrab_window = NULL; +} + +/** + * gdk_keyboard_grab_info_libgtk_only: + * @grab_window: location to store current grab window + * @owner_events: location to store boolean indicating whether + * the @owner_events flag to gdk_keyboard_grab() was %TRUE. + * + * Determines information about the current keyboard grab. + * This is not public API and must not be used by applications. + * + * Return value: %TRUE if this application currently has the + * keyboard grabbed. + **/ +gboolean +gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events) +{ + if (gdk_keyboard_xgrab_window) + { + if (grab_window) + *grab_window = (GdkWindow *)gdk_keyboard_xgrab_window; + if (owner_events) + *owner_events = gdk_keyboard_xgrab_owner_events; + + return TRUE; + } + else + return FALSE; +} + +/** + * _gdk_xgrab_check_unmap: + * @window: a #GdkWindow + * @serial: serial from Unmap event (or from NextRequest(display) + * if the unmap is being done by this client.) + * + * Checks to see if an unmap request or event causes the current + * grab window to become not viewable, and if so, clear the + * the pointer we keep to it. + **/ +void +_gdk_xgrab_check_unmap (GdkWindow *window, + gulong serial) +{ + if (gdk_pointer_xgrab_window && serial >= gdk_pointer_xgrab_serial) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + GdkWindowObject *tmp = gdk_pointer_xgrab_window; + + + while (tmp && tmp != private) + tmp = tmp->parent; + + if (tmp) + gdk_pointer_xgrab_window = NULL; + } + + if (gdk_keyboard_xgrab_window && serial >= gdk_keyboard_xgrab_serial) + { + GdkWindowObject *private = GDK_WINDOW_OBJECT (window); + GdkWindowObject *tmp = gdk_keyboard_xgrab_window; + + + while (tmp && tmp != private) + tmp = tmp->parent; + + if (tmp) + gdk_keyboard_xgrab_window = NULL; + } +} + +/** + * _gdk_xgrab_check_destroy: + * @window: a #GdkWindow + * + * Checks to see if window is the current grab window, and if + * so, clear the current grab window. + **/ +void +_gdk_xgrab_check_destroy (GdkWindow *window) +{ + if ((GdkWindowObject *)window == gdk_pointer_xgrab_window) + gdk_pointer_xgrab_window = NULL; + + if ((GdkWindowObject *)window == gdk_keyboard_xgrab_window) + gdk_keyboard_xgrab_window = NULL; } /* diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index a495c51878..2035e2066f 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -165,6 +165,10 @@ GC _gdk_x11_gc_flush (GdkGC *gc); void _gdk_x11_initialize_locale (void); +void _gdk_xgrab_check_unmap (GdkWindow *window, + gulong serial); +void _gdk_xgrab_check_destroy (GdkWindow *window); + extern GdkDrawableClass _gdk_x11_drawable_class; extern Window _gdk_root_window; extern gboolean _gdk_use_xshm; @@ -177,10 +181,6 @@ extern gchar *_gdk_display_name; extern Window _gdk_leader_window; -extern GdkWindowObject *_gdk_xgrab_window; /* Window that currently holds the - * x pointer grab - */ - /* Used to detect not-up-to-date keymap */ extern guint _gdk_keymap_serial; diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 53779c08ce..4779cb3829 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -169,6 +169,8 @@ gdk_window_impl_x11_finalize (GObject *object) wrapper = (GdkWindowObject*) draw_impl->wrapper; + _gdk_xgrab_check_destroy (GDK_WINDOW (wrapper)); + if (!GDK_WINDOW_DESTROYED (wrapper)) { gdk_xid_table_remove (draw_impl->xid); @@ -794,7 +796,9 @@ _gdk_windowing_window_destroy (GdkWindow *window, } } else if (!recursing && !foreign_destroy) - XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); + { + XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window)); + } } /* This function is called when the XWindow is really gone. @@ -819,6 +823,8 @@ gdk_window_destroy_notify (GdkWindow *window) gdk_xid_table_remove (GDK_WINDOW_XID (window)); if (window_impl->focus_window) gdk_xid_table_remove (window_impl->focus_window); + + _gdk_xgrab_check_destroy (window); gdk_drawable_unref (window); } @@ -991,6 +997,13 @@ gdk_window_hide (GdkWindow *window) private = (GdkWindowObject*) window; + /* We'll get the unmap notify eventually, and handle it then, + * but checking here makes things more consistent if we are + * just doing stuff ourself. + */ + _gdk_xgrab_check_unmap (window, + NextRequest (GDK_WINDOW_XDISPLAY (window))); + /* You can't simply unmap toplevel windows. */ switch (private->window_type) { diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 2b659a4677..c38607a39c 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -980,6 +980,121 @@ gtk_main_iteration_do (gboolean blocking) return TRUE; } +/* private libgtk to libgdk interfaces + */ +gboolean gdk_pointer_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events); +gboolean gdk_keyboard_grab_info_libgtk_only (GdkWindow **grab_window, + gboolean *owner_events); + +static void +rewrite_events_translate (GdkWindow *old_window, + GdkWindow *new_window, + gdouble *x, + gdouble *y) +{ + gint old_origin_x, old_origin_y; + gint new_origin_x, new_origin_y; + + gdk_window_get_origin (old_window, &old_origin_x, &old_origin_y); + gdk_window_get_origin (new_window, &new_origin_x, &new_origin_y); + + *x += new_origin_x - old_origin_x; + *y += new_origin_y - old_origin_y; +} + +GdkEvent * +rewrite_event_for_window (GdkEvent *event, + GdkWindow *new_window) +{ + event = gdk_event_copy (event); + + switch (event->type) + { + case GDK_SCROLL: + rewrite_events_translate (event->any.window, + new_window, + &event->scroll.x, &event->scroll.y); + break; + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + rewrite_events_translate (event->any.window, + new_window, + &event->button.x, &event->button.y); + break; + case GDK_MOTION_NOTIFY: + rewrite_events_translate (event->any.window, + new_window, + &event->motion.x, &event->motion.y); + break; + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + case GDK_PROXIMITY_IN: + case GDK_PROXIMITY_OUT: + break; + + default: + return event; + } + + g_object_unref (event->any.window); + event->any.window = g_object_ref (new_window); + + return event; +} + +/* If there is a pointer or keyboard grab in effect with owner_events = TRUE, + * then what X11 does is deliver the event normally if it was going to this + * client, otherwise, delivers it in terms of the grab window. This function + * rewrites events to the effect that events going to the same window group + * are delivered normally, otherwise, the event is delivered in terms of the + * grab window. + */ +static GdkEvent * +rewrite_event_for_grabs (GdkEvent *event) +{ + GdkWindow *grab_window; + GtkWidget *event_widget, *grab_widget;; + gboolean owner_events; + + switch (event->type) + { + case GDK_SCROLL: + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + case GDK_BUTTON_RELEASE: + case GDK_MOTION_NOTIFY: + case GDK_PROXIMITY_IN: + case GDK_PROXIMITY_OUT: + if (!gdk_pointer_grab_info_libgtk_only (&grab_window, &owner_events) || + !owner_events) + return NULL; + break; + + case GDK_KEY_PRESS: + case GDK_KEY_RELEASE: + if (!gdk_keyboard_grab_info_libgtk_only (&grab_window, &owner_events) || + !owner_events) + return NULL; + break; + + default: + return NULL; + } + + event_widget = gtk_get_event_widget (event); + gdk_window_get_user_data (grab_window, (void**) &grab_widget); + + if (grab_widget && + gtk_main_get_window_group (grab_widget) != gtk_main_get_window_group (event_widget)) + return rewrite_event_for_window (event, grab_window); + else + return NULL; +} + void gtk_main_do_event (GdkEvent *event) { @@ -987,6 +1102,7 @@ gtk_main_do_event (GdkEvent *event) GtkWidget *grab_widget; GtkWindowGroup *window_group; GdkEvent *next_event; + GdkEvent *rewritten_event = NULL; GList *tmp_list; /* If there are any events pending then get the next one. @@ -1045,14 +1161,24 @@ gtk_main_do_event (GdkEvent *event) return; } + + /* If pointer or keyboard grabs are in effect, munge the events + * so that each window group looks like a separate app. + */ + rewritten_event = rewrite_event_for_grabs (event); + if (rewritten_event) + { + event = rewritten_event; + event_widget = gtk_get_event_widget (event); + } + window_group = gtk_main_get_window_group (event_widget); + /* Push the event onto a stack of current events for * gtk_current_event_get(). */ current_events = g_list_prepend (current_events, event); - window_group = gtk_main_get_window_group (event_widget); - /* If there is a grab in effect... */ if (window_group->grabs) @@ -1198,6 +1324,9 @@ gtk_main_do_event (GdkEvent *event) tmp_list = current_events; current_events = g_list_remove_link (current_events, tmp_list); g_list_free_1 (tmp_list); + + if (rewritten_event) + gdk_event_free (rewritten_event); } gboolean diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index e6d2166802..bdc50b99df 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -1048,6 +1048,8 @@ range_grab_add (GtkRange *range, { /* we don't actually gtk_grab, since a button is down */ + gtk_grab_add (GTK_WIDGET (range)); + range->layout->grab_location = location; range->layout->grab_button = button; @@ -1058,6 +1060,8 @@ range_grab_add (GtkRange *range, static void range_grab_remove (GtkRange *range) { + gtk_grab_remove (GTK_WIDGET (range)); + range->layout->grab_location = MOUSE_OUTSIDE; range->layout->grab_button = 0; @@ -1305,8 +1309,18 @@ gtk_range_button_release (GtkWidget *widget, { GtkRange *range = GTK_RANGE (widget); - range->layout->mouse_x = event->x; - range->layout->mouse_y = event->y; + if (event->window == range->event_window) + { + range->layout->mouse_x = event->x; + range->layout->mouse_y = event->y; + } + else + { + gdk_window_get_pointer (range->event_window, + &range->layout->mouse_x, + &range->layout->mouse_y, + NULL); + } if (range->layout->grab_button == event->button) { @@ -1318,7 +1332,7 @@ gtk_range_button_release (GtkWidget *widget, gtk_range_remove_step_timer (range); if (grab_location == MOUSE_SLIDER) - update_slider_position (range, event->x, event->y); + update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y); /* Flush any pending discontinuous/delayed updates */ gtk_range_update_value (range); -- 2.30.2